package com.guoz.excel;


import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * 解析Excel文件
 * @Author guoz
 * @param <T>
 */
public class ResolveExcel<T> implements Iterable {

    private static final String SUFFIX_2003 = ".xls";
    private static final String SUFFIX_2007 = ".xlsx";

    private Workbook workbook;

    // 表格总数
    private int numOfSheet = 0;
    // 当前遍历的表格数目
    private int positionOfSheet = 0;
    // 当前的表格
    private Sheet sheet;

    // 当前表的总行数
    private int lastNumOfRow = 0;
    // 当前表遍历的行数
    private int positionOfRow = 1;

    private Class clazz;

    /**
     * @param file excel文件对象
     * @param clazz 实现了IConvertRowToEntity 接口的实体类
     */
    public ResolveExcel(MultipartFile file, Class clazz ) throws Exception {
        // todo 判断目标实体类是否实现了 IConvertRowToEntity 接口
        if (! (Arrays.asList(clazz.getInterfaces()).contains(IConvertRowToEntity.class))) {
            throw new Exception("实体类未实现 IConvertRowToEntity 接口 ");
        }
        this.clazz = clazz;
        String originalFilename = file.getOriginalFilename();
        // todo 检验文件格式
        if (originalFilename.endsWith(SUFFIX_2003)) {
            workbook = new HSSFWorkbook(file.getInputStream());
        } else if (originalFilename.endsWith(SUFFIX_2007)) {
            workbook = new XSSFWorkbook(file.getInputStream());
        }
        if (workbook == null)
            throw new Exception("文件格式错误");
        // todo 获取所有的工作表的的数量
        numOfSheet = workbook.getNumberOfSheets();
        if (numOfSheet <= 0)
            throw new Exception("文件不能为空！");
        // todo 获取第一张表格信息
        sheet = workbook.getSheetAt(positionOfSheet++);
        lastNumOfRow = sheet.getLastRowNum();
    }

    @Override
    public Iterator iterator() {
        return new Inner();
    }

    class Inner implements Iterator<T> {
        @Override
        public boolean hasNext() {
            return (positionOfRow <= lastNumOfRow || positionOfSheet < numOfSheet);
        }

        @Override
        public T next() {
            if (!hasNext())
                return null;
            Row row = null;
            if (positionOfRow <= lastNumOfRow) {
                // todo 获取当前行
                row = sheet.getRow(positionOfRow++);
            } else if (positionOfSheet < numOfSheet) {
                // todo 当前行越界， 查询下一个表格
                positionOfRow = 1;
                sheet = workbook.getSheetAt(positionOfSheet++);
                lastNumOfRow = sheet.getLastRowNum();
                row = sheet.getRow(positionOfRow++);
            }
            try {
                // todo 进行实体类转换
                return (T) ((IConvertRowToEntity) clazz.newInstance()).getEntity(row);
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
                return null;
            }
        }
    }
}
